package com.doge;

import java.awt.Point;

import MapEditor.EditorFileOperations;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.MoveToAction;
import com.badlogic.gdx.scenes.scene2d.ui.Table;

import enemies.AngryCabbage;
import enemies.BookBeast;
import enemies.DistractedSquirrel;
import enemies.Fairy;
import enemies.FlameDude;
import enemies.MovingFireball;
import enemies.OneArmedSkeleton;
import enemies.SassyVikingGenie;
import enemies.SleepyDragon;

public class Overworld extends Stage implements Screen, InputProcessor{

	public Main parent;
	public SpriteBatch batch;
	public TextureRegion grass;
	public BitmapFont font;
	String printMsg;
	public Tile[][] tiles;
	//public boolean update;
	public int mapX, mapY;
	public Player p;
	public int regionHeight;
	public int regionWidth;
	public float deltaSum;
	public int direction;
	public float animationTime;
	int keyUp;
	int keyCode;
	Table mapTable = new Table();
	ShapeRenderer shape = new ShapeRenderer();
	
	/**
	 * 
	 * @param parent
	 */
	public Overworld(Main parent){
		this.parent = parent;
		this.p = parent.p;
		font = new BitmapFont();
		printMsg = "wow. such grass.";
		//update = true;
		mapX = Settings.mapStageDimX;
		mapY = Settings.mapStageDimY;
		batch = new SpriteBatch();
		
		//tiles = new Tile[mapY][mapX];
		
		try{
			tiles = EditorFileOperations.LoadMapFromFile("TESTMAP");
		}catch(Exception e)
		{
			e.printStackTrace();

			this.printMsg = "Failed to load map";
			return;
		}
		
		animationTime = 0;
		keyUp = 0;
		keyCode = 0;
		
		//we should remove this map loading bullshit and make it a parameter or something
		//tiles = MapLoader.LoadMap(parent, Gdx.files.internal("data/map2.map"));
		
		regionWidth = Gdx.graphics.getWidth()/tiles.length;
		regionHeight = Gdx.graphics.getHeight()/tiles[0].length;

		
		deltaSum = 0;
		
		this.addActor(mapTable);
		//draw tiles
		mapTable.clearChildren();
		//mapTable.debug();
		
		//set up tiles
		mapTable.setPosition(0, Gdx.graphics.getHeight());
		
		int pixy = Gdx.graphics.getHeight()-regionHeight;
		
		for(int x = 0; x < Settings.mapDim*Settings.mapDim; ++x)
		{
			int i = x/Settings.mapDim;
			int y = x%Settings.mapDim;
		
			tiles[i][y].pixx = (x%Settings.mapDim)*regionWidth;
			tiles[i][y].pixy = pixy;
			tiles[i][y].regionHeight = regionHeight;
			tiles[i][y].regionWidth  = regionWidth;
			
			//if(i == 0 || y == 0 || y == Settings.mapDim || x == Settings.mapDim )
			//	tiles[i][y].borderTile = true;	
			
			//tiles[i][y] = new GridSquare(t);//,displayGrid);
			//tiles[i][y].setBounds(tiles[i][y].pixx, pixy, 32, 32);
			//tiles[i][y].addListener(new MapTileListener(tiles[i][y]));	
			mapTable.add(tiles[i][y]);
			
			if(y == (Settings.mapDim-1))
			{	
				mapTable.row();
				pixy -= regionHeight;
			}
		}
		
		setCharTarget(tiles[10][10]);
		p.setPosition(p.target.x, p.target.y);
	}

	public void render(float delta) {
		super.draw();
		deltaSum+=delta;
		if(deltaSum>.0133337){
			
			batch.begin();
			//if(update){
			//	drawTiles(regionWidth, regionHeight);
			//	update = false;
			//}
			if(p.moving){
				animationTime+=delta;
				moveChar(direction);
			}
			else if(keyUp != keyCode)
				keyDown(keyCode);
			batch.draw(p.t,p.getX()+(regionWidth/2),p.getY(),(int)(regionWidth*.7),regionHeight);
			//font.draw(spriteBatch, "MAIN MENU", Gdx.graphics.getWidth()/2,400);
			font.draw(batch, printMsg, Gdx.graphics.getWidth()/2 - font.getBounds(printMsg).width/2,10+font.getXHeight());
			batch.end();
			deltaSum = 0;
		}
	}

	@Override
	public void resize(int width, int height) {
		//batch.begin();
		//drawTiles(regionWidth, regionHeight);
		//batch.end();
	}

	@Override
	public void show() {
		// TODO Auto-generated method stub

	}

	@Override
	public void hide() {
		// TODO Auto-generated method stub

	}

	@Override
	public void pause() {
		// TODO Auto-generated method stub

	}

	@Override
	public void resume() {
		// TODO Auto-generated method stub

	}
/*
	public void drawTiles(float regionWidth,float regionHeight){
		/*int x = 0;
		int y = 0;
		for(int i = 0; i < mapY; i++){
			for(int j = 0; j < mapX; j++){
				//todo: debug: change to allow tile to draw itself
				batch.draw(tiles[i][j].textures.get(0),x,y,regionWidth,regionHeight);
				if(tiles[i][j].occupied)
					batch.draw(tiles[i][j].character.textureRegion,x,y,regionWidth,regionHeight);
				x+=regionWidth;
			}
			x = 0;
			y+=regionHeight;
		}//*\
		
		
		for(int x = 0; x < tiles.length; ++x)
			for(int y = 0; y < tiles[0].length; ++y)
				tiles[x][y].draw(batch, 127);
	}*/

	//directional handling
	public boolean keyDown(int keycode){
		//System.out.println(keycode);
		keyCode = keycode;
		if(!p.moving){
			switch(keycode){
			case Keys.A:
				moveLeft();
				break;
			case Keys.W:
				moveUp();
				break;
			case Keys.S:
				moveDown();
				break;
			case Keys.D:
				moveRight();
				break;
			}
			//System.out.println("break?");
		}

		keyUp = 0;
		return true;
	}

	public boolean keyUp(int keycode){
		keyUp = keycode;
		//System.out.println("keyup: "+keycode);
		
		switch(keycode)
		{
		case Keys.E:
		//case Keys.ENTER:
			Gdx.input.setInputProcessor(parent.skillupScreen);
			parent.setScreen(parent.skillupScreen);
			break;
		}
		
		return true;
	}

	/* tiles[x][y]
	 * tiles[2][3] =
	 * 
	 * 0 1 2
	 * 0 1 2 
	 */
	//movement handling methods, triggered by keyDown
	
	public void moveUp(){
		if(checkBounds(p.position.x-1,p.position.y,1)){
			setCharTarget(tiles[p.position.x-1][p.position.y]);
			//p.position = tiles[p.position.x-1][p.position.y];
			checkmob();
			//p.target = new Point((int)p.position.pixx-(regionHeight/2), (int)p.position.pixy);//(p.position.x*regionHeight));
			//update = true;
			p.moving = true;
			direction = 1;
			moveChar(direction);
		}
	}

	public void moveDown(){
		if(checkBounds(p.position.x+1,p.position.y,2)){
			setCharTarget(tiles[p.position.x+1][p.position.y]);
			//p.position = tiles[p.position.x+1][p.position.y];
			checkmob();
			//p.target = new Point((int)p.position.pixx-(regionHeight/2), (int)p.position.pixy);// p.position.x*regionHeight);
			//update = true;
			p.moving = true;
			direction = 2;
			moveChar(direction);
		}
	}

	public void moveRight(){
		if(checkBounds(p.position.x,p.position.y+1,3)){
			setCharTarget(tiles[p.position.x][p.position.y+1]);
			//p.position = tiles[p.position.x][p.position.y+1];
			checkmob();
			//p.target = new Point((int)p.position.pixx-(regionHeight/2), (int)p.position.pixy);// p.position.x*regionHeight);
			//update = true;
			p.moving = true;
			direction = 3;

			moveChar(direction);
		}
	}

	public void moveLeft(){
		if(checkBounds(p.position.x,p.position.y-1,4)){
			setCharTarget(tiles[p.position.x][p.position.y-1]);
			//p.position = tiles[p.position.x][p.position.y-1];
			checkmob();
			//p.target = new Point((int)p.position.pixx-(regionHeight/2), (int)p.position.pixy);//p.position.x*regionHeight);
			
			p.moving = true;
			//update = true;
			direction = 4;
			moveChar(direction);
		}
	}

	public void checkmob()
	{
		if(tiles[p.position.x][p.position.y].occupied)
		{
			Gdx.input.setInputProcessor(parent.fightStage);
			parent.fightStage.setCharacters(tiles[p.position.x][p.position.y].character);
			parent.setScreen(parent.fightStage);
			tiles[p.position.x][p.position.y].occupied = false;
			tiles[p.position.x][p.position.y].character = null;
		}
	}
	
	
	public void setCharTarget(Tile t)
	{
		p.position = t;
		p.target = getPoint(t);
	}
	
	public Point getPoint(Tile t)
	{
		return new Point((int)t.pixx-(regionHeight/2), (int)t.pixy);
	}
	
	//handles animations in certain directions depending on direction
	public void moveChar(int direction){
		
		switch(direction){
		//moving down
		case 2:
			if (animationTime>.33)
				p.t = parent.textures.playerMove;
			if(animationTime>.66){
				p.t = parent.textures.player;
				animationTime = 0;
			}
			if(p.getY()-p.target.y>2)
				p.setPosition(p.getX(), p.getY()-2f);
			else {
				p.setPosition(p.target.x, p.target.y);
				p.moving = false;
			}
			break;
			//moving up
		case 1:
			if (animationTime>.33)
				p.t = parent.textures.playerUpMove;
			if(animationTime>.66){
				p.t = parent.textures.playerUp;
				animationTime = 0;
			}
			if(p.target.y-p.getY()>2)
				p.setPosition(p.getX(), p.getY()+2f);
			else {
				p.setPosition(p.target.x, p.target.y);
				p.moving = false;
			}
			break;
			//moving left
		case 4:
			if (animationTime>.33)
				p.t = parent.textures.playerLeftMove;
			if(animationTime>.66){
				p.t = parent.textures.playerLeft;
				animationTime = 0;
			}

			if(p.getX() - p.target.x>2)
				p.setPosition(p.getX()-2f, p.getY());
			else {
				p.setPosition(p.target.x, p.target.y);
				p.moving = false;
			}
			break;
			//moving right	
		case 3:
			if (animationTime>.33)
				p.t = parent.textures.playerRightMove;
			if(animationTime>.66){
				p.t = parent.textures.playerRight;
				animationTime = 0;
			}
			if(p.target.x - p.getX()>2)
				p.setPosition(p.getX()+2f, p.getY());
			else {
				p.setPosition(p.target.x, p.target.y);
				p.moving = false;
			}
			break;
		}

		//update = true;
		//		if(p.getX() == p.target.x && p.getY() == p.target.y)
		//			p.moving = false;
	}

	
	//down up left right
	public boolean checkBounds(int x, int y, int direction){
		//up right down left
		int realDir = 0;
		if(direction == 2) realDir = 2;
		else if(direction == 3) realDir = 1;
		else if(direction == 4) realDir = 3;
		
		if(x>mapX-1 )
			return false;
		if(x<0)
			return false;
		if(y>mapY-1)
			return false;
		if(y<0)
			return false;
		/*
		if(!tiles[y][x].walkable)
			return false;*/
		
		//TODO: ADD COLLISION
		//if(tiles[x][y].borderTile || tiles[p.position.x][p.position.y].borderTile)
		//	return false;
	
		if(!tiles[p.position.x][p.position.y].tileEntry[realDir])
			return false;
		
		//north east south west
		if(realDir == 0) realDir = 2;
		else if(realDir == 1) realDir = 3;
		else if(realDir == 2) realDir = 0;
		else if(realDir == 3) realDir = 1;

		if(!tiles[x][y].tileEntry[realDir])
			return false;
		
		return true;
	}

}
